package com.winsdom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.winsdom.context.BaseContext;
import com.winsdom.dto.CategoryTreeNodes;
import com.winsdom.dto.contract.*;
import com.winsdom.entity.*;
import com.winsdom.mapper.*;
import com.winsdom.result.PageResult;
import com.winsdom.result.Result;
import com.winsdom.service.IContractService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.winsdom.vo.contract.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 合同主表 服务实现类
 * </p>
 *
 * @author
 * @since 2025-05-12
 */
@Service
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements IContractService {

    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private UserProjectsMapper userProjectsMapper;
    @Autowired
    private BillingConfigMapper billingConfigMapper;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private FeeCategoryMapper feeCategoryMapper;
    @Autowired
    private ExpenditureMapper expenditureMapper;
    @Autowired
    private BillingAssociationMapper billingAssociationMapper;
    @Autowired
    private PropertyInfoMapper propertyInfoMapper;
    @Autowired
    private FeeFormulaMapper feeFormulaMapper;
    @Autowired
    private ThreeTablesMapper threeTablesMapper;
    @Autowired
    private ReadingRecordMapper readingRecordMapper;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private TenantMoveHistoryMapper tenantMoveHistoryMapper;
    @Override
    public Result getContractList(ContractDto contractDto) {
        //获取当前账号授权的楼盘的资源列表
        Integer userId = BaseContext.getCurrentId();
        List<UserProjects> userProjects = userProjectsMapper.selectList(new LambdaQueryWrapper<UserProjects>()
                .eq(UserProjects::getUserId, userId));
        HashSet<Long> objects = new HashSet<>();   //资源ID
        for (UserProjects userProject : userProjects){
            List<Long> ids=contractMapper.getForCategoryIds(userProject.getCategoryId());
            for(Long id:ids){
                objects.add(id);
            }
        }
        if(userProjects==null && userProjects.size()==0 ){
            return Result.error("您当前账号没有管理楼盘!");
        }
        List<Long> collect = objects.stream().collect(Collectors.toList());
        if( collect.size()==0){
            return Result.success();
        }
        contractDto.setCategoryIds(collect);

        int num = (contractDto.getPageNum() - 1) * contractDto.getPageSize();
        int temp=contractDto.getPageNum();
        contractDto.setPageNum(num);
        List<ContractVo> list = contractMapper.getContract(contractDto);
        Long count=contractMapper.getContractForCount(contractDto);

        return Result.success(new PageResult(count,list,temp,contractDto.getPageSize()));
    }

    @Override
    public Result getContractDetail(Long contractId) {
        List<BillingConfigVo> list=billingConfigMapper.selectForBillingConfig(contractId);
        return Result.success(list);
    }

    @Override
    @Transactional
    public Result invalidContract(Long contractId) {
        contractMapper.update(null,new UpdateWrapper<Contract>()
                .eq("contract_id",contractId)
                .set("contract_status",0).set("invalid_reason","作废").set("invalid_date", LocalDate.now()));
        List<BillingConfig> billingConfigs = billingConfigMapper.selectList(new LambdaQueryWrapper<BillingConfig>().eq(BillingConfig::getContractId, contractId));
        for (BillingConfig billingConfig : billingConfigs) {
            billingConfigMapper.update(null,new UpdateWrapper<BillingConfig>()
                    .eq("config_id",billingConfig.getConfigId())
                    .set("status",0));
        }
        return Result.success("作废成功");
    }

    @Override
    public Result getList() {
        ContractDetailVo contractDetailVo = new ContractDetailVo();

        List<CustomervO> customervOList=customerMapper.selectForList();  //客户列表
        contractDetailVo.setCustomerList(customervOList);

        Integer userId = BaseContext.getCurrentId();
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getId, userId));
        List<UserProjects> userProjects = userProjectsMapper.selectList(new LambdaQueryWrapper<UserProjects>()  //查询当前账号授权的楼盘的列表
                .eq(UserProjects::getUserId, userId));
        List<Long> collect = userProjects.stream().map(userProject -> userProject.getCategoryId()).collect(Collectors.toList());
        List<CategoryTreeNodes> authorizedResourceTree = getAuthorizedResourceTree(sysUser.getCategoryId(), new HashSet<>(collect));
        contractDetailVo.setCategoryList(authorizedResourceTree);

        List<FeeCategoryDto> feeCategoryDtoList=feeCategoryMapper.selectListForIds();
        List<FeeCategoryDto> feeCategoryIds = feeCategoryDtoList.stream().distinct().collect(Collectors.toList());
        contractDetailVo.setFeeCategoryList(feeCategoryIds);
        return Result.success(contractDetailVo);
    }

    public List<CategoryTreeNodes> getAuthorizedResourceTree(Long orgId, Set<Long> authorizedBuildingIds) {
        // 1. 查询所有分类数据
        List<Category> allCategories = categoryMapper.selectList(null);

        // 2. 转换为节点映射
        Map<Long, CategoryTreeNodes> idNodeMap = new HashMap<>();
        for (Category category : allCategories) {
            CategoryTreeNodes node = new CategoryTreeNodes();
            BeanUtils.copyProperties(category, node);
            node.setChildren(new ArrayList<>());
            idNodeMap.put(node.getId(), node);
        }

        // 3. 构建父子关系
        for (CategoryTreeNodes node : idNodeMap.values()) {
            CategoryTreeNodes parent = idNodeMap.get(node.getParentId());
            if (parent != null) {
                parent.getChildren().add(node);
            }
        }

        //  4. 从 orgId 本身作为根节点开始过滤
        CategoryTreeNodes root = idNodeMap.get(orgId);
        if (root == null) {
            return Collections.emptyList(); // orgId 不存在
        }

        CategoryTreeNodes filtered = filterResourceUnderAuthorizedBuildings(root, authorizedBuildingIds);
        if (filtered == null) {
            return Collections.emptyList(); // 无授权资源
        }

        //  返回带 orgId 的整棵子树
        return Collections.singletonList(filtered);
    }
    private CategoryTreeNodes filterResourceUnderAuthorizedBuildings(CategoryTreeNodes node, Set<Long> authorizedBuildingIds) {
        // 如果当前节点是楼盘且不在授权范围，整个树都不保留
        if (node.getType() == 3 && !authorizedBuildingIds.contains(node.getId())) {
            return null;
        }

        // 递归过滤子节点
        List<CategoryTreeNodes> newChildren = new ArrayList<>();
        for (CategoryTreeNodes child : node.getChildren()) {
            CategoryTreeNodes filteredChild = filterResourceUnderAuthorizedBuildings(child, authorizedBuildingIds);
            if (filteredChild != null) {
                newChildren.add(filteredChild);
            }
        }

        node.setChildren(newChildren);

        // 满足保留条件：
        // 1. 是资源节点（type == 6）
        // 2. 或者有子节点（说明有资源后代）
        if (node.getType() == 6 || !newChildren.isEmpty()) {
            return node;
        }

        return null;
    }

    @Override
    public Result getExpenditureList(ExpenditureDto expenditureDto) {
        List<ExpenditureVo> list = null;
        Integer userId = BaseContext.getCurrentId();
        List<UserProjects> userProjects = userProjectsMapper.selectList(new LambdaQueryWrapper<UserProjects>()  //查询当前账号授权的楼盘的列表
                .eq(UserProjects::getUserId, userId));
        List<Long> categoryIds = userProjects.stream().map(userProject -> userProject.getCategoryId()).collect(Collectors.toList());
        List<PropertyInfo> propertyInfos = propertyInfoMapper.selectCategoryIds(categoryIds);
        List<Long> propertyInfoIds = propertyInfos.stream().map(propertyInfo -> propertyInfo.getId()).collect(Collectors.toList());
        List<BillingAssociation> billingAssociations = billingAssociationMapper.selectpropertyInfoIds(propertyInfoIds);
        if(billingAssociations==null || billingAssociations.size()==0){
            return Result.success(list);
        }
        List<Integer> expenditureIds = billingAssociations.stream().map(billingAssociation -> billingAssociation.getExpenditureId()).distinct().collect(Collectors.toList());
        expenditureDto.setExpenditureIds(expenditureIds);

        list=expenditureMapper.selectListForParams(expenditureDto);
        return Result.success(list);
    }

    @Override
    public Result getFeeFormulaList(Integer expenditureId, Integer type) {
        List<FeeFormula> list=null;
        if(type==1){
            list= feeFormulaMapper.selectList(new LambdaQueryWrapper<FeeFormula>().eq(FeeFormula::getExpenditureId, expenditureId).eq(FeeFormula::getType, 1));
        }
        if(type==2){
            list = feeFormulaMapper.selectList(new LambdaQueryWrapper<FeeFormula>().eq(FeeFormula::getExpenditureId, expenditureId).eq(FeeFormula::getType, 2));
        }

        return Result.success(list);
    }

    @Override
    public Result getThreeTables(Integer expenditureId, Long categoryId) {
        Expenditure expenditure = expenditureMapper.selectOne(new LambdaQueryWrapper<Expenditure>().eq(Expenditure::getExpenditureId, expenditureId).eq(Expenditure::getStatus, 1));
        if (expenditure == null) {
            return Result.error("系统错误!");
        }

        String chargingName = expenditure.getChargingType();
        // 2. 类型转换（使用常量定义更规范）
        Integer chargingType = null;
        switch (chargingName) {
            case "水费":
                chargingType = 0;
                break;
            case "电费":
                chargingType = 1;
                break;
            case "气费":
                chargingType = 2;
                break;
            default:
                Result.error("不支持的收费类型: " + chargingName);
        }

        List<ThreeTables> list = threeTablesMapper.selectList(new LambdaQueryWrapper<ThreeTables>().eq(ThreeTables::getCategoryId, categoryId).eq(ThreeTables::getType, chargingType).eq(ThreeTables::getStatus,1));
        if(list==null || list.size()==0){
            return Result.error("请在选择的资源中添加对应的三表");
        }
        for (ThreeTables threeTables : list){
            List<ReadingRecord> readingRecords = readingRecordMapper.selectList(new LambdaQueryWrapper<ReadingRecord>().eq(ReadingRecord::getTableId, threeTables.getId()));
            if(readingRecords!=null && !readingRecords.isEmpty()){
                //初始读数默认为三表的最后一次抄表数据。如果没有抄表数据，则默认为三表中录入的初始读数。
                threeTables.setSwot(readingRecords.get(0).getCurrentReading());
            }
        }
        return Result.success(list);
    }

    @Override
    @Transactional
    public Result addContract(AddContractDto contractDto) {

        Resource resource = resourceMapper.selectOne(new LambdaQueryWrapper<Resource>().eq(Resource::getCategoryId, contractDto.getContract().getCategoryId()));
        if(resource==null){
            return Result.error("系统出错!");
        }
        if(contractDto.getContract().getRoleType()==2 && resource.getResourceStatus().equals("未接房")){
            return Result.error("该资源无业主，无法迁入租户");
        }
        if(contractDto.getContract().getRoleType()==2 && resource.getResourceStatus().equals("非空置")){
            return Result.error("该资源已出租，无法迁入新租户");
        }
        Category category = categoryMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getId, contractDto.getContract().getCategoryId()));
        if(category.getStatus()==0){
            return Result.error("该资源已停用，不能进行迁入操作");
        }
        if(contractDto.getBillingConfigList()==null || contractDto.getBillingConfigList().size()==0){
            return Result.error("计费项目不能为空");
        }

        Contract contract = new Contract();

        Contract contract1 = contractMapper.selectOne(new LambdaQueryWrapper<Contract>().eq(Contract::getContractNumber, contractDto.getContract().getContractNumber()));
        if(contract1!=null){
            return Result.error("合同编号已存在");
        }

        BeanUtils.copyProperties(contractDto.getContract(), contract);
        contract.setContractStatus(1);
        contract.setGenerateDate(LocalDate.now());
        contractMapper.insert(contract);  //插入合同主表

        for(BillingConfig billingConfigDto : contractDto.getBillingConfigList()){
            BillingConfig billingConfig = new BillingConfig();
            BeanUtils.copyProperties(billingConfigDto,billingConfig);
            billingConfig.setStatus(1);
            billingConfig.setCreateTime(LocalDateTime.now());
            billingConfig.setUpdateTime(LocalDateTime.now());
            billingConfigMapper.insert(billingConfig);   //插入计费配置
        }

        TenantMoveHistory tenantMoveHistory = new TenantMoveHistory();
        tenantMoveHistory.setCustomerId(contract.getCustomerId());
        if(contract.getRoleType()==1){
            tenantMoveHistory.setRoleName("业主");
        }
        if(contract.getRoleType()==2){
            tenantMoveHistory.setRoleName("租户");
        }
        tenantMoveHistory.setContractNumber(contract.getContractNumber());

        Customer customer = customerMapper.selectById(contract.getCustomerId());
        tenantMoveHistory.setPhone(customer.getMobilePhone());
        tenantMoveHistory.setMoveInDate(LocalDate.now());
        tenantMoveHistoryMapper.insert(tenantMoveHistory);


        if(contract.getRoleType()==1 && resource.getResourceStatus().equals("未接房")){
            resource.setResourceStatus("空置");
            resource.setUpdateTime(LocalDateTime.now());
            resourceMapper.updateById(resource);
        }
        if(contract.getRoleType()==2 && resource.getResourceStatus().equals("未接房")){
            resource.setResourceStatus("非空置");
            resource.setUpdateTime(LocalDateTime.now());
            resourceMapper.updateById(resource);
        }
        return Result.success();
    }

    @Override
    @Transactional
    public Result updateContract(AddContractDto contractDto) {
        Contract contract = contractMapper.selectOne(new LambdaQueryWrapper<Contract>().eq(Contract::getContractNumber, contractDto.getContract().getContractNumber()));
        if(contract!=null){
            return Result.error("合同编号重复，请重新输入");
        }
        contract=  new Contract();
        Contract contract1 = contractMapper.selectOne(new LambdaQueryWrapper<Contract>().eq(Contract::getContractNumber, contractDto.getContract().getContractNumber()));
        if(contract1!=null){
            return Result.error("合同编号已存在");
        }
        BeanUtils.copyProperties(contractDto.getContract(),contract);
        contractMapper.updateById(contract);

        if(contractDto.getBillingConfigList()==null || contractDto.getBillingConfigList().size()==0){
            return Result.error("计费项目不能为空");
        }
        billingConfigMapper.delete(new LambdaQueryWrapper<BillingConfig>().eq(BillingConfig::getContractId, contract.getContractId()));
        for(BillingConfig billingConfigDto : contractDto.getBillingConfigList()){
            BillingConfig billingConfig = new BillingConfig();
            BeanUtils.copyProperties(billingConfigDto,billingConfig);
            billingConfig.setStatus(1);
            billingConfig.setCreateTime(LocalDateTime.now());
            billingConfig.setUpdateTime(LocalDateTime.now());
            billingConfigMapper.insert(billingConfig);   //插入计费配置
        }
        return Result.success();
    }

}
